home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
elk-2_0.lha
/
elk-2.0
/
src
/
special.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-02
|
11KB
|
480 lines
/* Special forms
*/
#include "scheme.h"
static Object Sym_Else;
Init_Special () {
Define_Symbol (&Sym_Else, "else");
}
Object P_Quote (argl) Object argl; {
return Car (argl);
}
Object Quasiquote (x, level) Object x; {
Object form, list, tail, cell, qcar, qcdr, ret;
TC_Prolog;
if (TYPE(x) != T_Pair)
return x;
if (EQ(Car (x), Sym_Unquote)) {
x = Cdr (x);
if (TYPE(x) != T_Pair)
Primitive_Error ("bad unquote form: ~s", x);
if (level) {
ret = Cons (Car (x), Null);
ret = Quasiquote(ret, level-1);
ret = Cons (Sym_Unquote, ret);
} else {
TC_Disable;
ret = Eval (Car (x));
TC_Enable;
}
return ret;
} else if (TYPE(Car (x)) == T_Pair
&& EQ(Car (Car (x)), Sym_Unquote_Splicing)) {
GC_Node6;
qcdr = Cdr (x);
form = list = tail = cell = Null;
x = Car (x);
if (TYPE(Cdr (x)) != T_Pair)
Primitive_Error ("bad unquote-splicing form: ~s", x);
if (level) {
GC_Link2 (list, qcdr);
list = Quasiquote(Cdr (x), level-1);
list = Cons (Sym_Unquote_Splicing, list);
qcdr = Quasiquote(qcdr, level);
list = Cons (list, qcdr);
GC_Unlink;
return list;
}
GC_Link6 (x, qcdr, form, list, tail, cell);
TC_Disable;
form = Eval (Car (Cdr (x)));
TC_Enable;
for ( ; TYPE(form) == T_Pair; tail = cell, form = Cdr (form)) {
cell = Cons (Car (form), Null);
if (Nullp (list))
list = cell;
else
(void)P_Setcdr (tail, cell);
}
qcdr = Quasiquote (qcdr, level);
GC_Unlink;
if (Nullp (list))
return qcdr;
(void)P_Setcdr (tail, qcdr);
return list;
} else {
GC_Node3;
qcar = qcdr = Null;
GC_Link3 (x, qcar, qcdr);
if (EQ(Car (x), Sym_Quasiquote)) /* hack! */
++level;
qcar = Quasiquote (Car (x), level);
qcdr = Quasiquote (Cdr (x), level);
list = Cons (qcar, qcdr);
GC_Unlink;
return list;
}
}
Object P_Quasiquote (argl) Object argl; {
return Quasiquote (Car (argl), 0);
}
Object P_Begin (forms) Object forms; {
GC_Node;
TC_Prolog;
if (Nullp (forms))
return Null;
GC_Link (forms);
TC_Disable;
for ( ; !Nullp (Cdr (forms)); forms = Cdr (forms))
(void)Eval (Car (forms));
GC_Unlink;
TC_Enable;
return Eval (Car (forms));
}
Object P_Begin1 (forms) Object forms; {
register n;
Object r, ret;
GC_Node;
TC_Prolog;
GC_Link (forms);
TC_Disable;
for (n = 1; !Nullp (Cdr (forms)); n = 0, forms = Cdr (forms)) {
r = Eval (Car (forms));
if (n)
ret = r;
}
GC_Unlink;
TC_Enable;
r = Eval (Car (forms));
return n ? r : ret;
}
Object P_If (argl) Object argl; {
Object cond, ret;
GC_Node;
TC_Prolog;
GC_Link (argl);
TC_Disable;
cond = Eval (Car (argl));
TC_Enable;
if (Truep(cond))
ret = Eval (Car (Cdr (argl)));
else
ret = Begin (Cdr (Cdr (argl)));
GC_Unlink;
return ret;
}
Object P_Case (argl) Object argl; {
Object ret, key, clause, select;
GC_Node;
TC_Prolog;
GC_Link (argl);
ret = False;
TC_Disable;
key = Eval (Car (argl));
for (argl = Cdr (argl); !Nullp (argl); argl = Cdr (argl)) {
clause = Car (argl);
Check_List (clause);
if (Nullp (clause))
Primitive_Error ("empty clause");
select = Car (clause);
if (EQ(select, Sym_Else)) {
if (!Nullp (Cdr (argl)))
Primitive_Error ("`else' not in last clause");
if (Nullp (Cdr (clause)))
Primitive_Error ("no forms in `else' clause");
} else if (TYPE(select) == T_Pair) {
select = P_Memv (key, select);
} else
select = P_Eqv (key, select);
if (Truep (select)) {
clause = Cdr (clause);
TC_Enable;
ret = Nullp (clause) ? True : Begin (clause);
break;
}
}
TC_Enable;
GC_Unlink;
return ret;
}
Object P_Cond (argl) Object argl; {
Object ret, clause, guard;
int else_clause = 0;
GC_Node3;
TC_Prolog;
ret = False;
clause = guard = Null;
GC_Link3 (argl, clause, guard);
TC_Disable;
for ( ; !Nullp (argl); argl = Cdr (argl)) {
clause = Car (argl);
Check_List (clause);
if (Nullp (clause))
Primitive_Error ("empty clause");
guard = Car (clause);
if (EQ(guard, Sym_Else)) {
if (!Nullp (Cdr (argl)))
Primitive_Error ("`else' not in last clause");
if (Nullp (Cdr (clause)))
Primitive_Error ("no forms in `else' clause");
else_clause++;
} else
guard = Eval (Car (clause));
if (Truep (guard)) {
clause = Cdr (clause);
if (!else_clause && !Nullp (clause) &&
EQ(Car (clause), Intern ("=>"))) {
clause = Cdr (clause);
if (Nullp (clause) || !Nullp (Cdr (clause)))
Primitive_Error ("syntax error after =>");
clause = Eval (Car (clause));
Check_Procedure (clause);
guard = Cons (guard, Null);
TC_Enable;
ret = Funcall (clause, guard, 0);
} else {
TC_Enable;
ret = Nullp (clause) ? guard : Begin (clause);
}
break;
}
}
TC_Enable;
GC_Unlink;
return ret;
}
Object General_Junction (argl, and) Object argl; register and; {
Object ret;
GC_Node;
TC_Prolog;
ret = and ? True : False;
if (Nullp (argl))
return ret;
GC_Link (argl);
TC_Disable;
for ( ; !Nullp (Cdr (argl)); argl = Cdr (argl)) {
ret = Eval (Car (argl));
if (and != Truep (ret))
break;
}
TC_Enable;
if (Nullp (Cdr (argl)))
ret = Eval (Car (argl));
GC_Unlink;
return ret;
}
Object P_And (argl) Object argl; {
return General_Junction (argl, 1);
}
Object P_Or (argl) Object argl; {
return General_Junction (argl, 0);
}
Object P_Do (argl) Object argl; {
Object tail, b, val, test, frame, newframe, len, ret;
register local_vars;
GC_Node6;
TC_Prolog;
b = test = frame = newframe = Null;
GC_Link6 (argl, tail, b, test, frame, newframe);
TC_Disable;
for (tail = Car (argl); !Nullp (tail); tail = Cdr (tail)) {
Check_List (tail);
b = Car (tail);
if (Nullp (b))
Primitive_Error ("bad initialization form");
val = P_Cdr (b);
Check_List (val);
b = Car (b);
Check_Type (b, T_Symbol);
if (!Nullp (val))
val = Eval (Car (val));
if (!EQ(Assq (b, frame), False))
Primitive_Error ("~s: duplicate variable binding", b);
frame = Add_Binding (frame, b, val);
}
if (local_vars = !Nullp (frame))
Push_Frame (frame);
test = Car (Cdr (argl));
Check_Type (test, T_Pair);
while (1) {
b = Eval (Car (test));
if (Truep (b))
break;
(void)Begin (Cdr (Cdr (argl)));
if (!local_vars)
continue;
newframe = Null;
for (tail = Car (argl); !Nullp (tail); tail = Cdr (tail)) {
b = Car (tail);
val = Cdr (b);
len = P_Length (val);
val = FIXNUM(len) > 1 ? Car (Cdr (val)) : Car (b);
newframe = Add_Binding (newframe, Car (b), Eval (val));
}
Pop_Frame ();
Push_Frame (newframe);
}
Check_List (Cdr (test));
TC_Enable;
ret = Begin (Cdr (test));
if (local_vars)
Pop_Frame ();
GC_Unlink;
return ret;
}
Object General_Let (argl, disc) Object argl; {
Object frame, b, binding, val, tail, ret;
GC_Node5;
TC_Prolog;
frame = b = val = Null;
GC_Link5 (argl, frame, b, val, tail);
TC_Disable;
for (tail = Car (argl); !Nullp (tail); tail = Cdr (tail)) {
Check_List (tail);
b = Car (tail);
if (Nullp (b))
Primitive_Error ("bad binding form");
val = P_Cdr (b);
Check_List (val);
if (!Nullp (val) && !Nullp (Cdr (val)))
Primitive_Error ("bad binding form");
b = Car (b);
Check_Type (b, T_Symbol);
if (!Nullp (val))
val = Car (val);
if (disc == 0) {
if (!Nullp (val))
val = Eval (val);
} else if (disc == 1) {
Push_Frame (frame);
if (!Nullp (val))
val = Eval (val);
Pop_Frame ();
} else if (disc == 2)
val = Null;
binding = Assq (b, frame);
if (disc != 1 && !EQ(binding, False))
Primitive_Error ("~s: duplicate variable binding", b);
if (disc == 1 && !EQ(binding, False))
Cdr (binding) = val;
else
frame = Add_Binding (frame, b, val);
}
Push_Frame (frame);
if (disc == 2) {
for (tail = Car (argl); !Nullp (tail); tail = Cdr (tail)) {
b = Car (tail);
val = Cdr (b);
if (Nullp (val))
continue;
val = Car (val);
b = Lookup_Symbol (Car (b), 1);
val = Eval (val);
Cdr (b) = val;
SYMBOL(Car (b))->value = val;
}
}
TC_Enable;
ret = Begin (Cdr (argl));
Pop_Frame ();
GC_Unlink;
return ret;
}
Object Named_Let (argl) Object argl; {
Object b, val, tail, vlist, vtail, flist, ftail, cell;
GC_Node6;
TC_Prolog;
tail = vlist = vtail = flist = ftail = Null;
GC_Link6 (argl, tail, vlist, vtail, flist, ftail);
TC_Disable;
for (tail = Car (Cdr (argl)); !Nullp (tail); tail = Cdr (tail)) {
Check_List (tail);
b = Car (tail);
if (Nullp (b))
Primitive_Error ("bad binding form");
val = P_Cdr (b);
Check_List (val);
if (Nullp (val) || !Nullp (Cdr (val)))
Primitive_Error ("bad binding form");
Check_Type (Car (b), T_Symbol);
if (!Nullp (val))
val = Car (val);
cell = Cons (val, Null);
if (Nullp (flist))
flist = cell;
else
(void)P_Setcdr (ftail, cell);
ftail = cell;
cell = Cons (Car (Car (tail)), Null);
if (Nullp (vlist))
vlist = cell;
else
(void)P_Setcdr (vtail, cell);
vtail = cell;
}
Push_Frame (Add_Binding (Null, Car (argl), Null));
tail = Cons (vlist, Cdr (Cdr (argl)));
tail = P_Lambda (tail);
COMPOUND(tail)->name = Car (argl);
b = Lookup_Symbol (Car (argl), 1);
Cdr (b) = tail;
SYMBOL(Car (argl))->value = tail;
TC_Enable;
tail = Funcall (tail, flist, 1);
Pop_Frame ();
GC_Unlink;
return tail;
}
Object P_Let (argl) Object argl; {
if (TYPE(Car (argl)) == T_Symbol)
return Named_Let (argl);
else
return General_Let (argl, 0);
}
Object P_Letseq (argl) Object argl; {
return General_Let (argl, 1);
}
Object P_Letrec (argl) Object argl; {
return General_Let (argl, 2);
}
Object Internal_Fluid_Let (bindings, argl) Object bindings, argl; {
Object b, sym, val, vec, ret;
WIND w;
GC_Node5;
if (Nullp (bindings))
return Begin (Cdr (argl));
b = sym = val = Null;
GC_Link5 (bindings, argl, b, sym, val);
Check_List (bindings);
b = Car (bindings);
if (Nullp (b))
Primitive_Error ("bad binding form");
sym = Car (b);
val = P_Cdr (b);
Check_List (val);
Check_Type (sym, T_Symbol);
if (!Nullp (val))
val = Car (val);
if (!Nullp (val))
val = Eval (val);
b = Lookup_Symbol (sym, 1);
vec = Make_Vector (3, Null);
VECTOR(vec)->data[0] = sym;
VECTOR(vec)->data[1] = The_Environment;
VECTOR(vec)->data[2] = Cdr (b);
Add_Wind (&w, vec, vec);
Cdr (b) = val;
SYMBOL(sym)->value = val;
ret = Internal_Fluid_Let (Cdr (bindings), argl);
Do_Wind (Car (w.inout));
GC_Unlink;
return ret;
}
Object P_Fluid_Let (argl) Object argl; {
Object ret;
WIND *first = First_Wind, *last = Last_Wind;
TC_Prolog;
TC_Disable;
ret = Internal_Fluid_Let (Car(argl), argl);
if (Last_Wind = last)
last->next = 0;
First_Wind = first;
TC_Enable;
return ret;
}